# Генераторы псевдослучайных чисел

Пакет `spire.random` содержит генераторы случайных чисел, подходящие для множества различных задач,
а также функциональный интерфейс для создания равномерного распределения значений.

## Генераторы псевдослучайных чисел

Трейт `mutable.Generator` представляет собой стратегию PRNG. 
Используя равномерно сгенерированные значения `Int` или `Long`, 
он может генерировать случайные значения, массивы значений и т.д. 
Определить генератор относительно легко.

По умолчанию генераторы не являются потокобезопасными. 
Синхронизированный генератор можно создать из несинхронизированного с помощью метода `sync`. 
Генераторы можно копировать, а их начальные значения сохранять и восстанавливать. 
Это позволяет пользователям создавать детерминированные потоки значений, 
используя одно и то же начальное значение. 
В общем, пользователям предпочтительнее создавать и использовать свои собственные генераторы, 
а не полагаться на один генератор в нескольких потоках.

Хотя трейт `mutable.Generator` предоставляет только низкоуровневые методы, такие как `nextInt`, 
он может создавать значения любого типа, используя класс типов `Dist[A]`, который будет обсуждаться ниже.

Трейт `immutable.Generator` похож на `mutable.Generator`, хотя хранимое в нем состояние является неизменным. 
Каждый раз, когда генерируется число, также возвращается новый генератор, 
что позволяет использовать эти генераторы в чисто функциональном контексте. 
Здесь также применимы те же примеры `Dist[A]`, которые использовались бы с изменяемым генератором.

## Создание случайных значений с помощью Dist\[A\]

Класс типов `Dist[A]` представляет собой стратегию генерации распределения значений `A` для данного экземпляра `Generator`. 
`Dist[A]` не дает никаких гарантий относительно того, как распределяются значения `A`
(например, он всегда может возвращать одно и то же значение). 
Пользователи, интересующиеся конкретными реализациями, должны использовать трейты 
`Uniform[A]`, `Gaussian[A]` и `Exponential[A]` для создания экземпляров `Dist[A]`, соответствующих их потребностям.

Сами объекты `Dist[A]` неизменяемы и создаются от генераторов (как изменяемых, так и неизменяемых). 
Их можно преобразовать с помощью `map`, `flatMap` и других комбинаторов. 
При наличии соответствующей структуры `A` с экземплярами `Dist[A]` также можно работать, как если бы они были значениями.

## Распределения

В настоящее время `spire.random` предоставляет классы типов `Uniform[A]`, `Gaussian[A]` и `Exponential[A]`, 
которые с учетом соответствующих параметров могут создавать экземпляры `Dist[A]`. 
Поскольку большинство типов имеют (приблизительно) бесконечное число возможных значений, 
на эти типы необходимо наложить границы и другие ограничения, 
прежде чем мы сможем с пользой говорить о (или реализовывать) распределения вероятностей в Spire.

- Учитывая `min` и `max`, экземпляр `Uniform[A]` может создать равномерно распределенный экземпляр `Dist[A]`.
- Учитывая `mean` и `stdDev`, экземпляр `Gaussian[A]` может создать `Dist[A]`, 
  значения которого распределяются в соответствии с желаемым распределением Гаусса.
- Учитывая `rate`, экземпляр `Gaussian[A]` может создать `Dist[A]`, 
  значения которого распределяются в соответствии с желаемым экспоненциальным распределением.

Например:

```dotty
object DistDemo:
  import spire.math.Complex
  import spire.random.Dist
  import spire.std.double.DoubleAlgebra
  
  val rng = spire.random.rng.Cmwc5()
  rng.nextLong() 
  
  // генерирует ассоциативный массив с от 10 до 20 записей
  given Dist[Map[Int, Complex[Double]]] =
    Dist.map[Int, Complex[Double]](10, 20)
  val m = rng.next[Map[Int, Complex[Double]]]
  
  // генерирует double в интервале [0.0, 1.0)
  val n = rng.next[Double]
  
  // генерирует комплексное число с действительной и мнимой частями в интервале [0.0, 1.0)
  val q = rng.next[Complex[Double]]
```

Предоставляется множество экземпляров по умолчанию, и для пользовательских типов легко создавать собственные экземпляры.

---

**Ссылки:**

- [Spire home page](https://typelevel.org/spire)
- [Spire User's Guide](https://typelevel.org/spire/guide.html)
